<?php
declare(strict_types=1);

namespace SixShop\Lakala\Entity;

use SixShop\Core\Entity\BaseEntity;
use SixShop\Lakala\Enum\ProfitShareOrderCMDTypeEnum;
use SixShop\Lakala\Enum\ProfitShareOrderStatusEnum;
use SixShop\Lakala\Enum\ReceiverStatusEnum;
use SixShop\Lakala\Facade\Config;
use SixShop\Lakala\Facade\LedgerService;
use SixShop\Lakala\Model\ProfitShareOrderModel;
use SixShop\Lakala\Model\ProfitShareReceiverModel;
use think\Paginator;
use function SixShop\Core\throw_logic_exception;

/**
 * @mixin ProfitShareOrderModel
 */
class ProfitShareOrderEntity extends BaseEntity
{
    public function getOrderList(array $params, array $pageAndLimit): Paginator
    {
        return $this->withSearch(['out_separate_no', 'status'], $params)
            ->append(['status_text'])
            ->paginate($pageAndLimit);
    }

    /**
     * @param int $userID
     * @param int $receiverID
     * @param float $amount
     * @return self
     */
    public function createOrder(int $userID, int $receiverID, float $amount): self
    {
        $receiver = ProfitShareReceiverModel::where([
            'id' => $receiverID,
            'user_id' => $userID,
            'status' => ReceiverStatusEnum::BOUND,
        ])->findOrEmpty();
        if ($receiver->isEmpty()) {
            throw_logic_exception('分账接收方不存在或未绑定');
        }
        $merInfo = LedgerService::queryLedgerMer($receiver->mer_cup_no, $receiver->org_id);
        $calculateData = $this->calculateOrder($amount, $merInfo->splitLowestRatio);
        $this->save([
            'merchant_no' => $receiver->mer_cup_no,
            'user_id' => $userID,
            'total_amt' => $calculateData['total_amt'],
            'lkl_org_no' => $receiver->org_id,
            'cal_type' => 0, // 按照指定金额
            'recv_merchant_no' => $receiver->mer_cup_no,
            'recv_no' => $receiver->receiver_no,
            'separate_value' => $calculateData['separate_value'],
            'status' => ProfitShareOrderStatusEnum::PENDING,
            'fee_amt' => $calculateData['fee_amt'],
            'cmd_type' => ProfitShareOrderCMDTypeEnum::SEPARATE,
        ]);
        return $this;
    }

    /**
     * 计算分账数据
     *
     * @param float $amount
     * @return array{total_amt:int, fee_amt:int, separate_value:int}
     */
    private function calculateOrder(float $amount, float $splitLowestRatio): array
    {
        $splitLowestRatio = bcsub(100, (string)$splitLowestRatio, 2);
        $fee = Config::getConfig('profit_share_fee');
        $feeAmt = bcmul((string)$amount, (string)$fee, 2);
        if (bccomp($feeAmt, '1') == -1) {
            $feeAmt = 1;
        }
        $seprateValue = bcmul((string)$amount, '100', 2);
        $seprateValue = bcsub($seprateValue, $feeAmt);
        $totalAmout = bcmul($seprateValue, '100', 2);
        $totalAmout = bcdiv($totalAmout, (string)$splitLowestRatio);
        return [
            'total_amt' => $totalAmout,
            'fee_amt' => (int)$feeAmt,
            'separate_value' => (int)$seprateValue,
        ];
    }
}